﻿using up6.db.model;
using up6.utils;

namespace up6.db.store;

/// <summary>
/// 文件块处理器
/// 优化文件创建逻辑，按文件实际大小创建
/// </summary>
public class FileBlockWriter
{
    public StorageType storage;//写入器类型
    public long m_lenLoc;       //文件总大小。

    //文件读写锁，防止多个用户同时上传相同文件时，出现创建文件的错误
    static ReaderWriterLock m_writeLock = new ReaderWriterLock();

    public FileBlockWriter()
    {
        this.storage = StorageType.IO;
    }

    /// <summary>
    /// 根据文件大小创建文件。参数，pathSvr,lenLoc
    /// 注意：多个用户同时上传相同文件时，可能会同时创建相同文件。
    /// </summary>
    public virtual async Task<string> makeAsync(FileInf file)
    {
        //文件名称为空 => 抛出异常
        if (string.IsNullOrEmpty(file.pathSvr)) throw new IOException("pathSvr is empty");
        if (!File.Exists(file.pathSvr))
        {
            var pos = file.pathSvr.LastIndexOf('\\');
            if (-1 == pos) pos = file.pathSvr.LastIndexOf('/');
            var dir = file.pathSvr.Substring(0, pos);
            //自动创建目录
            if (!Directory.Exists(dir))
            {
                System.Diagnostics.Debug.WriteLine(string.Format("路径不存在：{0}", dir));
                PathTool.createDirectory(dir);
            }
            else
            {
                System.Diagnostics.Debug.WriteLine(string.Format("路径存在：{0}", dir));
            }

            var fs = File.OpenWrite(file.pathSvr);
            fs.SetLength(file.lenLoc);
            if (file.encrypt) fs.SetLength(file.lenLocSec);
            fs.Close();
        }
        return "";
    }

    /// <summary>
    /// 续传文件，参数：pathSvr,blockOffset
    /// </summary>
    /// <param name="fileRange">文件块</param>
    /// <param name="path">远程文件完整路径。d:\www\web\upload\201204\10\md5.exe</param>
    public virtual async Task<string> writeAsync(FileInf file, Stream fileStm)
    {
        if (!File.Exists(file.pathSvr)) throw new IOException("io error pathSvr not exist");
        //文件已存在，写入数据
        FileStream fs = File.OpenWrite(file.pathSvr);
        //加密存储->使用块加密偏移
        if (file.encrypt) fs.Seek(file.blockOffsetCry, SeekOrigin.Begin);
        else fs.Seek(file.blockOffset, SeekOrigin.Begin);
        byte[] ByteArray = new byte[fileStm.Length];
        fileStm.Seek(0, SeekOrigin.Begin);
        await fileStm.ReadAsync(ByteArray, 0, (int)fileStm.Length);
        await fs.WriteAsync(ByteArray, 0, (int)fileStm.Length);
        fs.Flush();
        fs.Close();
        return file.pathSvr;
    }

    public virtual async Task<bool> writeLastPartAsync(FileInf file)
    {
        return true;
    }
}